# backend\api\vision_api.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
视力记录API - 完整修复版本
修复所有类型错误和基线对比计算问题
"""

from flask import Blueprint, request, jsonify, current_app, send_file
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime, date, time
from typing import Optional, Dict, Any, List
import pandas as pd
from io import BytesIO
import json
import logging
from sqlalchemy import and_, or_, func
from sqlalchemy.exc import IntegrityError

from backend.infrastructure.database import db
from backend.models.vision import VisionRecord
from backend.models.student import Student
from backend.models.student_extension import StudentExtension
from backend.models.vision_log import VisionRecordLog, LogAction
from backend.config.config_manager import ConfigManager
from backend.services.vision_calculation import (
    calculate_vision_metrics, 
    set_baseline, 
    find_baseline
)
from backend.decorators.auth_decorators import require_permissions
from flask_jwt_extended import jwt_required
from backend.services.unified_log_service import log_service

# 初始化配置管理器
config_manager = ConfigManager()
VISION_CALCULATION_CONFIG = config_manager.get_vision_calculation_config()

# 日志配置
logger = logging.getLogger(__name__)
LOG_CONFIG = config_manager.get_unified_log_config()
LOG_FRONTEND_CONFIG = config_manager.get_log_frontend_config()

vision_api = Blueprint('vision_api', __name__)

@vision_api.route('/api/vision_records/list', methods=['GET'])
def get_vision_records():
    """获取视力记录列表"""
    try:
        student_id = request.args.get('student_id', type=int)
        page = request.args.get('page', 1, type=int)
        
        # 使用配置驱动的分页设置，符合三层架构原则
        pagination_config = config_manager.get_vision_api_config().get('pagination', {})
        default_per_page = pagination_config.get('default_per_page', 10)
        max_per_page = pagination_config.get('max_per_page', 100)
        per_page = min(request.args.get('per_page', default_per_page, type=int), max_per_page)
        
        query = VisionRecord.query
        
        if student_id:
            query = query.filter_by(student_id=student_id)
        
        # 按测量日期降序排列
        query = query.order_by(VisionRecord.measure_date.desc())
        
        # 分页
        pagination = query.paginate(
            page=page, 
            per_page=per_page, 
            error_out=False
        )
        
        records = []
        for record in pagination.items:
            record_dict = record.to_dict()
            
            # 添加学生信息
            if record.student:
                record_dict['student_name'] = record.student.name
                record_dict['education_id'] = record.student.education_id
                record_dict['school'] = record.student.school
                record_dict['class_name'] = record.student.class_name
            
            records.append(record_dict)
        
        return jsonify({
            'success': True,
            'data': records,
            'total': pagination.total,
            'page': page,
            'per_page': per_page,
            'pages': pagination.pages
        })
        
    except Exception as e:
        return jsonify({'success': False, 'message': str(e)}), 500

@vision_api.route('/api/vision_records', methods=['POST'])
def create_vision_record():
    """创建视力记录"""
    try:
        data = request.get_json()
        
        # 验证必填字段 - 使用配置驱动
        def validate_required_fields_create(data):
            """创建记录时的必填字段验证 - 配置驱动"""
            validation_errors = []
            required_fields = config_manager.get_vision_api_validation_config("create")
            
            for field, error_message in required_fields.items():
                if not data.get(field):
                    validation_errors.append(error_message)
            
            return validation_errors
        
        # 验证视力字段数据
        def validate_vision_field_data(data):
            """验证视力字段数据的合理性"""
            validation_errors = []
            
            # 视力范围验证（4.0-5.3）
            vision_fields = ['right_eye_naked', 'left_eye_naked', 'right_eye_corrected', 'left_eye_corrected']
            for field in vision_fields:
                value = data.get(field)
                if value is not None:
                    try:
                        value = float(value)
                        if not (4.0 <= value <= 5.3):
                            validation_errors.append(f'{field} 值应在4.0-5.3范围内')
                    except (ValueError, TypeError):
                        validation_errors.append(f'{field} 应为有效数字')
            
            # 屈光度范围验证
            sphere_fields = ['right_sphere', 'left_sphere']
            for field in sphere_fields:
                value = data.get(field)
                if value is not None:
                    try:
                        value = float(value)
                        if not (-20.0 <= value <= 20.0):
                            validation_errors.append(f'{field} 值应在-20.0到+20.0范围内')
                    except (ValueError, TypeError):
                        validation_errors.append(f'{field} 应为有效数字')
            
            return validation_errors
        
        # 执行验证
        validation_errors = validate_required_fields_create(data)
        validation_errors.extend(validate_vision_field_data(data))
        
        if validation_errors:
            return jsonify({'success': False, 'error': '; '.join(validation_errors)}), 400
        
        # 创建记录
        record = VisionRecord()
        record.student_id = data['student_id']
        
        # 处理日期和时间字段
        if data.get('measure_date'):
            try:
                measure_date = datetime.strptime(data['measure_date'], '%Y-%m-%d').date()
                record.measure_date = measure_date  # type: ignore
            except ValueError:
                return jsonify({'success': False, 'error': '测量日期格式错误，应为YYYY-MM-DD'}), 400
        else:
            record.measure_date = date.today()  # type: ignore
            
        if data.get('measure_time'):
            try:
                measure_time = datetime.strptime(data['measure_time'], '%H:%M').time()
                record.measure_time = measure_time  # type: ignore
            except ValueError:
                return jsonify({'success': False, 'error': '测量时间格式错误，应为HH:MM'}), 400
            
        record.measure_location = data.get('measure_location')
        
        # 使用配置驱动的默认值
        defaults = config_manager.get_vision_api_defaults()
        record.measure_type = data.get('measure_type', defaults.get('measure_type', '常规检查'))
        record.measurer = data.get('measurer')
        record.is_baseline = data.get('is_baseline', defaults.get('is_baseline', False))
        
        # ✅修复：正确处理data_year字段
        if record.measure_date:  # type: ignore
            record.data_year = str(record.measure_date.year)  # type: ignore
        else:
            record.data_year = str(date.today().year)  # type: ignore
        
        # 视力数据
        record.right_eye_naked = data.get('right_eye_naked')
        record.left_eye_naked = data.get('left_eye_naked')
        record.right_eye_corrected = data.get('right_eye_corrected')
        record.left_eye_corrected = data.get('left_eye_corrected')
        
        # 屈光数据
        record.right_sphere = data.get('right_sphere')
        record.left_sphere = data.get('left_sphere')
        record.right_cylinder = data.get('right_cylinder')
        record.left_cylinder = data.get('left_cylinder')
        record.right_axis = data.get('right_axis')
        record.left_axis = data.get('left_axis')
        
        # 散瞳数据
        record.right_dilated_sphere = data.get('right_dilated_sphere')
        record.left_dilated_sphere = data.get('left_dilated_sphere')
        record.right_dilated_cylinder = data.get('right_dilated_cylinder')
        record.left_dilated_cylinder = data.get('left_dilated_cylinder')
        record.right_dilated_axis = data.get('right_dilated_axis')
        record.left_dilated_axis = data.get('left_dilated_axis')
        record.right_dilated_vision = data.get('right_dilated_vision')
        record.left_dilated_vision = data.get('left_dilated_vision')
        
        # 角膜曲率
        record.right_keratometry_K1 = data.get('right_keratometry_K1')
        record.left_keratometry_K1 = data.get('left_keratometry_K1')
        record.right_keratometry_K2 = data.get('right_keratometry_K2')
        record.left_keratometry_K2 = data.get('left_keratometry_K2')
        
        # 眼轴和前房深度
        record.right_axial_length = data.get('right_axial_length')
        record.left_axial_length = data.get('left_axial_length')
        record.right_anterior_depth = data.get('right_anterior_depth')
        record.left_anterior_depth = data.get('left_anterior_depth')
        
        # 其他信息
        record.eye_fatigue = data.get('eye_fatigue')
        record.other_info = data.get('other_info')
        record.equipment_model = data.get('equipment_model')
        record.remarks = data.get('remarks')
        
        # ✅新增：自动计算检查次数（measurement_sequence）
        try:
            # 查询同一学生的所有现有记录，按测量日期排序
            existing_records = VisionRecord.query.filter_by(
                student_id=record.student_id
            ).order_by(VisionRecord.measure_date).all()
            
            # 将新记录添加到列表中，重新按日期排序
            all_records = existing_records + [record]
            all_records.sort(key=lambda x: x.measure_date)
            
            # 重新为所有记录分配正确的序号（按日期顺序）
            for idx, rec in enumerate(all_records, 1):
                rec.measurement_sequence = idx  # type: ignore
            
            logger.info(f"学生{record.student_id}：重新计算{len(all_records)}条记录的检查次数，新记录为第{record.measurement_sequence}次")
            
        except Exception as seq_error:
            logger.error(f"计算检查次数失败: {seq_error}")
            # 失败时设置默认值
            record.measurement_sequence = 1  # type: ignore
        
        # SE计算通过calculate_vision_metrics统一处理，避免重复计算
        
        # 保存到数据库
        db.session.add(record)
        db.session.flush()  # 获取记录ID
        
        # ✅使用vision_calculation服务进行完整计算
        from backend.services.vision_calculation import calculate_vision_metrics
        
        try:
            calculate_vision_metrics(record)
        except Exception as calc_error:
            # 计算失败不影响记录创建，只记录警告
            logger.error(f"视力记录计算失败: {calc_error}")
        
        # 记录创建日志
        try:
            log = VisionRecordLog.log_create(
                record=record,
                operator=data.get('operator', '系统'),
                ip_address=request.remote_addr
            )
            if log:
                db.session.add(log)
        except Exception as log_error:
            logger.error(f"创建日志失败: {log_error}")

        db.session.commit()
        
        # ✅ 新增：确保学生扩展记录存在
        if record.measure_date:
            target_year = str(record.measure_date.year)
            try:
                from backend.services.student_extension_service import ensure_yearly_extension
                extension = ensure_yearly_extension(record.student_id, target_year)
                if extension:
                    logger.info(f"自动创建学生{record.student_id}的{target_year}年扩展记录")
                else:
                    logger.warning(f"学生{record.student_id}的{target_year}年扩展记录已存在或创建失败")
            except Exception as ext_error:
                print(f"⚠️ 创建学生扩展记录失败: {ext_error}")
        
        # 使用配置驱动的消息
        messages = config_manager.get_vision_api_messages()
        return jsonify({
            'success': True,
            'message': messages.get('create_success', '视力记录创建成功'),
            'data': record.to_dict()
        })
        
    except Exception as e:
        db.session.rollback()
        return jsonify({'success': False, 'error': str(e)}), 500

@vision_api.route('/api/vision_records/<int:record_id>', methods=['GET'])
def get_vision_record(record_id):
    """获取单个视力记录详情"""
    try:
        record = VisionRecord.query.get_or_404(record_id)
        
        record_dict = record.to_dict()
        
        # 添加学生信息
        if record.student:
            record_dict['student_name'] = record.student.name
            record_dict['education_id'] = record.student.education_id
            record_dict['school'] = record.student.school
            record_dict['class_name'] = record.student.class_name
        
        return jsonify({
            'success': True,
            'data': record_dict
        })
        
    except Exception as e:
        return jsonify({'success': False, 'message': str(e)}), 500

@vision_api.route('/api/vision_records/<int:record_id>', methods=['PUT'])
@jwt_required()
@require_permissions('vision:edit')
def update_vision_record(record_id):
    """更新视力记录"""
    try:
        record = VisionRecord.query.get_or_404(record_id)
        data = request.get_json()
        
        # 验证必填字段 - 使用配置驱动
        def validate_required_fields_update(data, existing_record):
            """更新记录时的必填字段验证 - 配置驱动"""
            validation_errors = []
            required_fields = config_manager.get_vision_api_validation_config("update")
            
            for field, error_message in required_fields.items():
                if field in data and not data[field]:
                    validation_errors.append(error_message)
            
            # 处理measure_type的默认值
            if 'measure_type' in data and not data['measure_type']:
                if not existing_record.measure_type:
                    defaults = config_manager.get_vision_api_defaults()
                    data['measure_type'] = defaults.get('measure_type', '常规检查')
            
            return validation_errors
        
        # 执行验证
        validation_errors = validate_required_fields_update(data, record)
        if validation_errors:
            return jsonify({'success': False, 'error': '; '.join(validation_errors)}), 400
        
        # 保存更新前的数据
        old_data = record.to_dict()
        
        # ✅修复：更新基本信息，确保类型安全
        if 'measure_date' in data and data['measure_date']:
            try:
                measure_date = datetime.strptime(data['measure_date'], '%Y-%m-%d').date()
                record.measure_date = measure_date  # type: ignore
                record.data_year = str(measure_date.year)  # type: ignore
            except ValueError:
                return jsonify({'success': False, 'error': '测量日期格式错误'}), 400
            
        if 'measure_time' in data:
            if data['measure_time']:
                try:
                    measure_time = datetime.strptime(data['measure_time'], '%H:%M').time()
                    record.measure_time = measure_time  # type: ignore
                except ValueError:
                    return jsonify({'success': False, 'error': '测量时间格式错误'}), 400
            else:
                record.measure_time = None  # type: ignore
            
        if 'measure_location' in data:
            record.measure_location = data['measure_location']
            
        if 'measure_type' in data:
            if data['measure_type']:
                record.measure_type = data['measure_type']
            elif not record.measure_type:
                defaults = config_manager.get_vision_api_defaults()
                record.measure_type = defaults.get('measure_type', '常规检查')
            
        if 'measurer' in data:
            if data['measurer']:
                record.measurer = data['measurer']
        
        if 'is_baseline' in data:
            record.is_baseline = data['is_baseline']
        
        # 更新视力数据
        def get_updateable_vision_fields():
            """获取可更新的视力字段列表 - 基于统一字段配置架构"""
            from backend.config.config_manager import ConfigManager
            config_manager = ConfigManager()
            
            # 基于医学检查流程的可更新字段分组
            field_group_names = [
                "basic_vision", "refraction_measurement", "dilated_refraction", "biometry_measurement"
            ]
            
            updateable_fields = []
            for group_name in field_group_names:
                group_fields = config_manager.get_vision_fields_by_group(group_name)
                updateable_fields.extend(group_fields)
            
            return updateable_fields
        
        vision_fields = get_updateable_vision_fields()
        
        for field in vision_fields:
            if field in data:
                setattr(record, field, data[field])
        
        # 更新其他信息
        if 'eye_fatigue' in data:
            record.eye_fatigue = data['eye_fatigue']
        if 'other_info' in data:
            record.other_info = data['other_info']
        if 'equipment_model' in data:
            record.equipment_model = data['equipment_model']
        if 'remarks' in data:
            record.remarks = data['remarks']
        
        # 更新时间戳
        record.updated_at = datetime.now()
        
        # 统一计算：SE值和视力指标
        from backend.services.vision_calculation import calculate_vision_metrics
        
        try:
            calculate_vision_metrics(record, force_recalculate=True)
        except Exception as calc_error:
            print(f"视力记录计算失败 (ID: {record.id}): {calc_error}")
        
        # 记录更新日志 - 在计算之后记录，保存完整的计算后数据
        try:
            log = VisionRecordLog.log_update(
                record=record,
                old_data=old_data,
                operator=data.get('operator', '系统'),
                ip_address=request.remote_addr
            )
            if log:
                db.session.add(log)
        except Exception as log_error:
            print(f"更新日志失败: {log_error}")
        
        # 保存到数据库
        db.session.commit()
        
        # 使用配置驱动的消息
        messages = config_manager.get_vision_api_messages()
        return jsonify({
            'success': True,
            'message': messages.get('update_success', '视力记录更新成功'),
            'data': record.to_dict()
        })
        
    except Exception as e:
        db.session.rollback()
        return jsonify({'success': False, 'error': str(e)}), 500

@vision_api.route('/api/vision_records/<int:record_id>', methods=['DELETE'])
@jwt_required()
@require_permissions('vision:delete')
def delete_vision_record(record_id):
    """删除视力记录 - 添加日志功能"""
    try:
        record = VisionRecord.query.get_or_404(record_id)
        
        # 修复：安全获取操作人信息，避免JSON解析错误
        operator = '系统'
        try:
            if request.json and isinstance(request.json, dict):
                operator = request.json.get('operator', '系统')
        except Exception as json_error:
            print(f"获取操作人信息失败，使用默认值: {json_error}")
        
        # 记录删除日志 - 使用日志模型方法
        try:
            log = VisionRecordLog.log_delete(
                record=record,
                operator=operator,
                ip_address=request.remote_addr
            )
            if log:
                db.session.add(log)
        except Exception as log_error:
            print(f"删除日志失败: {log_error}")
        
        # 删除记录
        db.session.delete(record)
        db.session.commit()
        
        return jsonify({
            'success': True,
            'message': '视力记录删除成功'
        })
        
    except Exception as e:
        db.session.rollback()
        print(f"删除视力记录失败: {e}")
        return jsonify({'success': False, 'error': str(e)}), 500

@vision_api.route('/api/vision_records/set_baseline', methods=['POST'])
def set_baseline_record():
    """设置基线记录"""
    try:
        data = request.get_json()
        student_id = data.get('student_id')
        record_id = data.get('record_id')
        
        if not student_id or not record_id:
            return jsonify({'success': False, 'message': '缺少必要参数'}), 400
        
        success = set_baseline(student_id, record_id)
        
        if success:
            return jsonify({
                'success': True,
                'message': '基线记录设置成功'
            })
        else:
            return jsonify({
                'success': False,
                'message': '基线记录设置失败'
            }), 400
            
    except Exception as e:
        return jsonify({'success': False, 'message': str(e)}), 500

@vision_api.route('/api/vision_records/get_baseline', methods=['GET'])
def get_baseline_record():
    """获取学生的基线记录"""
    try:
        student_id = request.args.get('student_id', type=int)
        
        if not student_id:
            return jsonify({'success': False, 'message': '缺少学生ID参数'}), 400
        
        baseline = find_baseline(student_id)
        
        if baseline:
            return jsonify({
                'success': True,
                'data': baseline.to_dict()
            })
        else:
            return jsonify({
                'success': True,
                'data': None,
                'message': '未找到基线记录'
            })
            
    except Exception as e:
        return jsonify({'success': False, 'message': str(e)}), 500

@vision_api.route('/api/vision_records/export', methods=['GET'])
@jwt_required()
@require_permissions('data:export')
def export_vision_records():
    """
    导出视力记录 - 支持Excel格式
    前端显示名：导出视力检查历史记录表
    """
    try:
        student_id = request.args.get('student_id', type=int)
        export_type = request.args.get('type', 'xlsx')  # 只支持Excel格式
        
        if not student_id:
            return jsonify({'success': False, 'message': '缺少学生ID参数'}), 400
        
        # 获取学生信息
        student = Student.query.get_or_404(student_id)
        
        # 获取该学生的所有视力记录，按日期降序
        records = VisionRecord.query.filter_by(student_id=student_id)\
                                   .order_by(VisionRecord.measure_date.desc())\
                                   .all()
        
        if export_type.lower() == 'xlsx':
            return export_to_excel(student, records)
        else:
            return jsonify({'success': False, 'message': '只支持Excel格式导出'}), 400
            
    except Exception as e:
        return jsonify({'success': False, 'message': str(e)}), 500

def export_to_excel(student, records):
    """
    导出为Excel格式 - 根据实际数据动态生成列
    """
    try:
        import io
        from flask import send_file
        from openpyxl import Workbook
        from openpyxl.styles import Font, Alignment, Border, Side
        
        # 创建工作簿
        wb = Workbook()
        ws = wb.active
        if ws is not None:
            ws.title = "视力检查历史记录表"
        
        # 设置样式
        title_font = Font(size=14, bold=True)
        header_font = Font(size=11, bold=True)
        center_align = Alignment(horizontal='center', vertical='center')
        border = Border(
            left=Side(style='thin'),
            right=Side(style='thin'),
            top=Side(style='thin'),
            bottom=Side(style='thin')
        )
        
        # 文档标题
        if ws is not None:
            ws.merge_cells('A1:G1')
            if ws['A1'] is not None:
                ws['A1'].font = title_font
                ws['A1'].alignment = center_align
                ws['A1'] = '视力检查历史记录表'
        
        # 学生基本信息 - 按技术文档B要求
        current_row = 3
        student_info = [
            ('教育ID号码', getattr(student, 'education_id', '') or ''),
            ('姓名', getattr(student, 'name', '') or ''),
            ('性别', getattr(student, 'gender', '') or ''),
            ('出生日期', student.birthday.strftime('%Y-%m-%d') if student.birthday else ''),
            ('身份证号码', getattr(student, 'id_card', '') or ''),
            ('学校', getattr(student, 'school', '') or '')
        ]
        
        # 学生信息分两行显示，每行3个字段
        for i in range(0, len(student_info), 3):
            col = 1
            for j in range(3):
                if i + j < len(student_info):
                    label, value = student_info[i + j]
                    if ws is not None:
                        cell = ws.cell(row=current_row, column=col, value=f"{label}：{value}")
                        if cell is not None:
                            cell.font = header_font
                            cell.alignment = center_align
                    col += 2
            current_row += 1
        
        # 动态分析数据中的有效字段
        def analyze_data_fields(records):
            """分析记录中的有效字段"""
            # 获取所有可能的字段配置
            all_possible_fields = [
                {"field": "measure_date", "display_name": "检查日期", "type": "date"},
                {"field": "measure_time", "display_name": "检查时间", "type": "time"},
                {"field": "measure_location", "display_name": "检查地点", "type": "text"},
                {"field": "measurer", "display_name": "检查人员", "type": "text"},
                {"field": "measure_type", "display_name": "检查类型", "type": "text"},
                {"field": "equipment_model", "display_name": "检查设备", "type": "text"},
                {"field": "right_eye_naked", "display_name": "右眼裸眼视力", "type": "float"},
                {"field": "left_eye_naked", "display_name": "左眼裸眼视力", "type": "float"},
                {"field": "right_eye_corrected", "display_name": "右眼矫正视力", "type": "float"},
                {"field": "left_eye_corrected", "display_name": "左眼矫正视力", "type": "float"},
                {"field": "right_sphere", "display_name": "右眼球镜度数", "type": "float"},
                {"field": "left_sphere", "display_name": "左眼球镜度数", "type": "float"},
                {"field": "right_cylinder", "display_name": "右眼柱镜度数", "type": "float"},
                {"field": "left_cylinder", "display_name": "左眼柱镜度数", "type": "float"},
                {"field": "right_axis", "display_name": "右眼轴位", "type": "float"},
                {"field": "left_axis", "display_name": "左眼轴位", "type": "float"},
                {"field": "right_se", "display_name": "右眼等效球镜", "type": "float"},
                {"field": "left_se", "display_name": "左眼等效球镜", "type": "float"},
                {"field": "right_dilated_sphere", "display_name": "右眼散瞳球镜", "type": "float"},
                {"field": "left_dilated_sphere", "display_name": "左眼散瞳球镜", "type": "float"},
                {"field": "right_dilated_cylinder", "display_name": "右眼散瞳柱镜", "type": "float"},
                {"field": "left_dilated_cylinder", "display_name": "左眼散瞳柱镜", "type": "float"},
                {"field": "right_dilated_axis", "display_name": "右眼散瞳轴位", "type": "float"},
                {"field": "left_dilated_axis", "display_name": "左眼散瞳轴位", "type": "float"},
                {"field": "right_axial_length", "display_name": "右眼眼轴长度", "type": "float"},
                {"field": "left_axial_length", "display_name": "左眼眼轴长度", "type": "float"},
                {"field": "right_anterior_depth", "display_name": "右眼前房深度", "type": "float"},
                {"field": "left_anterior_depth", "display_name": "左眼前房深度", "type": "float"},
                {"field": "right_keratometry_K1", "display_name": "右眼K1值", "type": "float"},
                {"field": "left_keratometry_K1", "display_name": "左眼K1值", "type": "float"},
                {"field": "right_keratometry_K2", "display_name": "右眼K2值", "type": "float"},
                {"field": "left_keratometry_K2", "display_name": "左眼K2值", "type": "float"},
                {"field": "comprehensive_vision_level", "display_name": "视力等级", "type": "text"},
                {"field": "vision_level", "display_name": "视力分级", "type": "text"},
                {"field": "eye_fatigue", "display_name": "眼疲劳情况", "type": "text"},
                {"field": "other_info", "display_name": "其他信息", "type": "text"},
                {"field": "remarks", "display_name": "备注", "type": "text"}
            ]
            
            valid_fields = []
            
            # 检查哪些字段在记录中有数据
            for field_config in all_possible_fields:
                field_name = field_config["field"]
                has_data = False
                
                # 检查是否有记录包含该字段的有效数据
                for record in records:
                    value = getattr(record, field_name, None)
                    if value is not None:
                        if isinstance(value, str) and value.strip():
                            has_data = True
                            break
                        elif not isinstance(value, str) and value:
                            has_data = True
                            break
                
                if has_data:
                    valid_fields.append(field_config)
            
            return valid_fields
        
        # 动态生成表头
        valid_fields = analyze_data_fields(records)
        
        # 如果没有找到有效字段，使用最基本的字段
        if not valid_fields:
            valid_fields = [
                {"field": "measure_date", "display_name": "检查日期", "type": "date"},
                {"field": "measure_location", "display_name": "检查地点", "type": "text"},
                {"field": "measurer", "display_name": "检查人员", "type": "text"}
            ]
        
        current_row += 1
        headers = [field["display_name"] for field in valid_fields]
        
        for col, header in enumerate(headers, 1):
            if ws is not None:
                cell = ws.cell(row=current_row, column=col, value=header)
                if cell is not None:
                    cell.font = header_font
                    cell.alignment = center_align
                    cell.border = border
        
        # 数据行 - 使用动态字段
        current_row += 1
        
        for record in records:
            row_data = []
            
            for field_config in valid_fields:
                field_name = field_config["field"]
                field_type = field_config["type"]
                # 根据字段类型格式化数据
                if field_name == "measure_date":
                    value = record.measure_date.strftime('%Y-%m-%d') if record.measure_date else ''
                elif field_name == "measure_time":
                    value = record.measure_time.strftime('%H:%M') if record.measure_time else ''
                elif field_type == "date":
                    field_value = getattr(record, field_name, None)
                    if field_value and hasattr(field_value, 'strftime'):
                        value = field_value.strftime('%Y-%m-%d')
                    else:
                        value = str(field_value) if field_value else ''
                elif field_type == "time":
                    field_value = getattr(record, field_name, None)
                    if field_value and hasattr(field_value, 'strftime'):
                        value = field_value.strftime('%H:%M')
                    else:
                        value = str(field_value) if field_value else ''
                else:
                    field_value = getattr(record, field_name, None)
                    if field_value is not None:
                        if hasattr(field_value, 'strftime'):
                            value = field_value.strftime('%Y-%m-%d')
                        else:
                            value = str(field_value)
                    else:
                        value = ''
                
                # 将处理好的值添加到行数据中
                row_data.append(value)
            
            # 将行数据写入Excel
            for col, value in enumerate(row_data, 1):
                if ws is not None:
                    cell = ws.cell(row=current_row, column=col, value=value)
                    if cell is not None:
                        cell.border = border
                        cell.alignment = center_align
            
            current_row += 1
        
        # 动态调整列宽 - 基于实际列数
        default_width = 15
        for col in range(1, len(headers) + 1):
            if ws is not None:
                ws.column_dimensions[chr(64 + col)].width = default_width
        
        # 保存到内存
        output = io.BytesIO()
        wb.save(output)
        output.seek(0)
        
        # 生成文件名
        filename = f"{student.name or '学生'}_{student.education_id or 'unknown'}_视力记录.xlsx"
        
        return send_file(
            output,
            as_attachment=True,
            download_name=filename,
            mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
        )
        
    except ImportError:
        return jsonify({'success': False, 'message': '缺少openpyxl库，请安装：pip install openpyxl'}), 500
    except Exception as e:
        return jsonify({'success': False, 'message': f'导出失败：{str(e)}'}), 500

@vision_api.route('/api/vision_records/<int:record_id>/export_excel', methods=['GET'])
@jwt_required()
@require_permissions('data:export')
def export_vision_record_excel(record_id):
    """
    导出单条视力记录为Excel格式
    前端显示名：导出当前视力检查记录
    """
    try:
        # 获取视力记录
        record = VisionRecord.query.get_or_404(record_id)
        
        # 获取学生信息
        student = Student.query.get_or_404(record.student_id)
        
        # 导出单条记录
        return export_to_excel(student, [record])
        
    except Exception as e:
        return jsonify({'success': False, 'message': f'导出失败：{str(e)}'}), 500

@vision_api.route('/api/vision_records/<int:record_id>/export_pdf', methods=['GET'])
@jwt_required()
@require_permissions('data:export')
def export_vision_record_pdf(record_id):
    """
    导出单条视力记录为专业医院格式PDF
    """
    try:
        # 获取视力记录
        record = VisionRecord.query.get_or_404(record_id)
        
        # 获取学生信息
        student = Student.query.get_or_404(record.student_id)
        
        # 使用专业PDF导出服务
        from backend.services.vision_pdf_export import create_vision_pdf_report
        
        # 生成PDF
        pdf_config = config_manager.get_registry_config("VISION_EXPORT_CONFIG", {}).get("pdf", {})
        pdf_buffer = create_vision_pdf_report(student, record, pdf_config)
        
        # 生成文件名
        filename = f"{student.name or '学生'}_{student.education_id or 'unknown'}_视力检查报告.pdf"
        
        return send_file(
            pdf_buffer,
            as_attachment=True,
            download_name=filename,
            mimetype='application/pdf'
        )
        
    except ImportError as e:
        return jsonify({'success': False, 'message': f'PDF生成模块未安装: {str(e)}'}), 500
    except Exception as e:
        return jsonify({'success': False, 'message': f'PDF导出失败: {str(e)}'}), 500

@vision_api.route('/api/vision_records/logs', methods=['GET'])
def get_vision_record_logs():
    """获取单条视力记录的操作日志 - 使用统一日志服务"""
    record_id = request.args.get('record_id', type=int)
    
    # ✅调用统一日志服务
    response_data, status_code = log_service.get_record_logs(
        LogModel=VisionRecordLog,
        record_id=record_id,
        order_by_field='operation_time',
        config=LOG_FRONTEND_CONFIG
    )
    
    return jsonify(response_data), status_code

@vision_api.route('/api/vision_records/logs_all', methods=['GET'])
@vision_api.route('/api/vision_records/logs/all', methods=['GET'])  # 兼容前端调用路径
def get_all_vision_record_logs():
    """获取某学生的所有视力记录操作日志 - 使用统一日志服务"""
    student_id = request.args.get('student_id', type=int)
    
    # 获取学生姓名用于消息显示
    student_name = None
    if student_id:
        try:
            student = Student.query.get(student_id)
            if student:
                student_name = student.name
        except Exception:
            pass
    
    # ✅调用统一日志服务
    response_data, status_code = log_service.get_student_all_logs(
        LogModel=VisionRecordLog,
        student_id=student_id,
        order_by_field='operation_time',
        config=LOG_FRONTEND_CONFIG,
        student_name=student_name
    )
    
    return jsonify(response_data), status_code

# ✅新增：统一日志配置接口
@vision_api.route('/api/students/get', methods=['GET'])
def get_student_info():
    """获取学生基本信息 - 支持多种ID类型查询"""
    try:
        # 兼容多种参数：student_id（数字），education_id（字符串）
        student_id = request.args.get('student_id', type=int)
        education_id = request.args.get('education_id', type=str)
        
        if not student_id and not education_id:
            return jsonify({'success': False, 'message': '缺少学生ID参数（需要 student_id 或 education_id）'}), 400
        
        # 查询学生信息
        if student_id:
            student = Student.query.get(student_id)
        else:
            student = Student.query.filter_by(education_id=education_id).first()
            
        if not student:
            return jsonify({'success': False, 'message': '未找到该学生'}), 404
        
        return jsonify({
            'success': True,
            'student': student.to_dict()
        })
        
    except Exception as e:
        return jsonify({'success': False, 'message': str(e)}), 500

# ✅通用数据类型转换函数 - 复用录入时的逻辑
def apply_restore_data_conversion(record_obj, data_dict):
    """恢复时的数据类型转换 - 仅转换，不计算"""
    for key, value in data_dict.items():
        if not hasattr(record_obj, key) or key == 'id':
            continue
        
        # 日期字段处理
        if key == 'measure_date' and value is not None:
            if isinstance(value, str):
                try:
                    if 'T' in value:
                        value = datetime.fromisoformat(value.replace('Z', '+00:00')).date()
                    else:
                        value = datetime.strptime(value, '%Y-%m-%d').date()
                except ValueError:
                    print(f"恢复时日期格式转换失败: {key}={value}")
                    continue
        
        # 时间字段处理
        elif key == 'measure_time' and value is not None:
            if isinstance(value, str):
                try:
                    if len(value) == 8:  # HH:MM:SS
                        value = datetime.strptime(value, '%H:%M:%S').time()
                    elif len(value) == 5:  # HH:MM
                        value = datetime.strptime(value, '%H:%M').time()
                except ValueError:
                    print(f"恢复时时间格式转换失败: {key}={value}")
                    continue
        
        # datetime字段处理
        elif key in ['created_at', 'updated_at'] and value is not None:
            if isinstance(value, str):
                try:
                    value = datetime.fromisoformat(value.replace('Z', '+00:00'))
                except ValueError:
                    print(f"恢复时datetime格式转换失败: {key}={value}")
                    continue
        
        # 设置值
        setattr(record_obj, key, value)

@vision_api.route('/api/vision_records/restore', methods=['POST'])
def restore_vision_record():
    """恢复视力记录 - 使用统一日志服务"""
    try:
        data = request.get_json()
        log_id = data.get('log_id')
        
        if not log_id:
            return jsonify({'success': False, 'message': '缺少日志ID参数'}), 400
        
        print(f"🔄 恢复视力记录: 日志ID={log_id}")
        
        # 使用统一日志服务处理恢复
        response_data, status_code = log_service.restore_record(
            LogModel=VisionRecordLog,
            RecordModel=VisionRecord,
            log_id=log_id,
            operator=data.get('operator', '系统'),
                ip_address=request.remote_addr
            )
        
        return jsonify(response_data), status_code
        
    except Exception as e:
        print(f"❌ 视力记录恢复失败: {e}")
        import traceback
        traceback.print_exc()
        return jsonify({'success': False, 'message': str(e)}), 500

@vision_api.route('/api/vision_records/restore_deleted', methods=['POST'])
def restore_deleted_vision_record():
    """恢复已删除的视力记录"""
    try:
        data = request.get_json()
        log_id = data.get('log_id')
        
        if not log_id:
            return jsonify({'success': False, 'message': '缺少日志ID参数'}), 400
        
        # 查询删除日志记录
        log = VisionRecordLog.query.get_or_404(log_id)
        
        if log.action != LogAction.DELETE:
            return jsonify({'success': False, 'message': '该日志不是删除操作'}), 400
        
        if not log.old_content:
            return jsonify({'success': False, 'message': '日志中无可恢复的内容'}), 400
        
        # 解析原始数据
        try:
            old_data = json.loads(log.old_content)
        except json.JSONDecodeError:
            return jsonify({'success': False, 'message': '日志数据格式错误'}), 400
        
        # 创建新记录
        new_record = VisionRecord()
        
        # 恢复数据（排除id字段）- 使用相同的类型转换逻辑，不计算
        apply_restore_data_conversion(new_record, old_data)
        
        # 保存新记录
        db.session.add(new_record)
        db.session.flush()  # 获取新记录ID
        
        # 记录恢复操作日志 - 使用统一日志服务
        try:
            restore_log = VisionRecordLog.log_restore(
                record_id=new_record.id,
                student_id=new_record.student_id,
                old_data={},  # 恢复前状态（记录不存在）
                restored_data=old_data,  # 恢复后状态
                operator=(request.json or {}).get('operator', '系统'),
                ip_address=request.remote_addr
            )
            if restore_log:
                db.session.add(restore_log)
        except Exception as log_error:
            print(f"记录恢复日志失败: {log_error}")
        
        db.session.commit()
        
        return jsonify({
            'success': True,
            'message': '已删除的视力记录恢复成功',
            'data': new_record.to_dict()
        })
        
    except Exception as e:
        db.session.rollback()
        return jsonify({'success': False, 'error': str(e)}), 500



